In [ ]:
# Identify necessary images to perform the following using only OPENCV library.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
from google.colab import files
import os
from scipy.signal import wiener


image = cv.imread('/content/drive/MyDrive/Colab Notebooks/Advanced Data Analytics/lab-image.webp')
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
plt.imshow(image)
plt.show
Out[ ]:
matplotlib.pyplot.show
def show(*args, **kwargs)
/usr/local/lib/python3.10/dist-packages/matplotlib/pyplot.pyDisplay all open figures.

Parameters
----------
block : bool, optional
    Whether to wait for all figures to be closed before returning.

    If `True` block and run the GUI main loop until all figure windows
    are closed.

    If `False` ensure that all figure windows are displayed and return
    immediately.  In this case, you are responsible for ensuring
    that the event loop is running to have responsive figures.

    Defaults to True in non-interactive mode and to False in interactive
    mode (see `.pyplot.isinteractive`).

See Also
--------
ion : Enable interactive mode, which shows / updates the figure after
      every plotting command, so that calling ``show()`` is not necessary.
ioff : Disable interactive mode.
savefig : Save the figure to an image file instead of showing it on screen.

Notes
-----
**Saving figures to file and showing a window at the same time**

If you want an image file as well as a user interface window, use
`.pyplot.savefig` before `.pyplot.show`. At the end of (a blocking)
``show()`` the figure is closed and thus unregistered from pyplot. Calling
`.pyplot.savefig` afterwards would save a new and thus empty figure. This
limitation of command order does not apply if the show is non-blocking or
if you keep a reference to the figure and use `.Figure.savefig`.

**Auto-show in jupyter notebooks**

The jupyter backends (activated via ``%matplotlib inline``,
``%matplotlib notebook``, or ``%matplotlib widget``), call ``show()`` at
the end of every cell by default. Thus, you usually don't have to call it
explicitly there.
No description has been provided for this image
In [ ]:
#  Sharpen and Blur the input image using cv.filter2D() and display the output for any 5 user defined kernels.

# Sharpening kernel
sharpen_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])

# Blurring kernels
blur_kernel_1 = np.ones((5,5),np.float32)/25
blur_kernel_2 = np.array([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) / 16
blur_kernel_3 = np.ones((3,3),np.float32)/9
blur_kernel_4 = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
blur_kernel_5 = np.array([[1/9, 1/9, 1/9], [1/9, 1/9, 1/9], [1/9, 1/9, 1/9]])

sharpened_image = cv.filter2D(src=image, ddepth=-1, kernel=sharpen_kernel)
blurred_image_1 = cv.filter2D(src=image, ddepth=-1, kernel=blur_kernel_1)
blurred_image_2 = cv.filter2D(src=image, ddepth=-1, kernel=blur_kernel_2)
blurred_image_3 = cv.filter2D(src=image, ddepth=-1, kernel=blur_kernel_3)
blurred_image_4 = cv.filter2D(src=image, ddepth=-1, kernel=blur_kernel_4)
blurred_image_5 = cv.filter2D(src=image, ddepth=-1, kernel=blur_kernel_5)
No description has been provided for this image
In [ ]:
image = cv.imread('/content/drive/MyDrive/Colab Notebooks/Advanced Data Analytics/noisy-image.png')
plt.imshow(image)
plt.show
Out[ ]:
matplotlib.pyplot.show
def show(*args, **kwargs)
/usr/local/lib/python3.10/dist-packages/matplotlib/pyplot.pyDisplay all open figures.

Parameters
----------
block : bool, optional
    Whether to wait for all figures to be closed before returning.

    If `True` block and run the GUI main loop until all figure windows
    are closed.

    If `False` ensure that all figure windows are displayed and return
    immediately.  In this case, you are responsible for ensuring
    that the event loop is running to have responsive figures.

    Defaults to True in non-interactive mode and to False in interactive
    mode (see `.pyplot.isinteractive`).

See Also
--------
ion : Enable interactive mode, which shows / updates the figure after
      every plotting command, so that calling ``show()`` is not necessary.
ioff : Disable interactive mode.
savefig : Save the figure to an image file instead of showing it on screen.

Notes
-----
**Saving figures to file and showing a window at the same time**

If you want an image file as well as a user interface window, use
`.pyplot.savefig` before `.pyplot.show`. At the end of (a blocking)
``show()`` the figure is closed and thus unregistered from pyplot. Calling
`.pyplot.savefig` afterwards would save a new and thus empty figure. This
limitation of command order does not apply if the show is non-blocking or
if you keep a reference to the figure and use `.Figure.savefig`.

**Auto-show in jupyter notebooks**

The jupyter backends (activated via ``%matplotlib inline``,
``%matplotlib notebook``, or ``%matplotlib widget``), call ``show()`` at
the end of every cell by default. Thus, you usually don't have to call it
explicitly there.
No description has been provided for this image
In [ ]:
# Mean Filtering
mean_filtered_image = cv.blur(image, (5,5))

# Gaussian Filter
gaussian_filtered_image = cv.GaussianBlur(image, (5,5), 0)

# Sobel Filter
sobel_right_kernal = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
sobel_down_kernal = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
sobel_left_kernal = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])
sobel_up_kernal = np.array([[1,2,1],[0,0,0],[-1,-2,-1]])



sobel_left_image = cv.filter2D(image,-1,sobel_left_kernal)
sobel_right_image = cv.filter2D(image,-1,sobel_right_kernal)
sobel_up_image = cv.filter2D(image,-1,sobel_up_kernal)
sobel_down_image = cv.filter2D(image,-1,sobel_down_kernal)

# Median Filter
median_filtered_image = cv.medianBlur(image, 5)

# Laplacian Filter
laplacian_filtered_image = cv.Laplacian(image, cv.CV_64F)
abs_laplacian = cv.convertScaleAbs(laplacian_filtered_image)

# Bilateral Filter
bilateral_filtered_image = cv.bilateralFilter(image, 9, 75, 75)

# Non-Local Means Filtering
dst = cv.fastNlMeansDenoisingColored(image, None, 10, 10, 7, 21)

# Other filtering techniques
# 1. Box Filter
box_filtered_image = cv.boxFilter(image, -1, (5,5))

# 2. Scharr Filter
scharrx_image = cv.Scharr(image, cv.CV_64F, 1, 0)
scharry_image = cv.Scharr(image, cv.CV_64F, 0, 1)
abs_scharrx = cv.convertScaleAbs(scharrx_image)
abs_scharry = cv.convertScaleAbs(scharry_image)

# 3. Adaptive Gaussian Thresholding (for grayscale images)
gray_image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
adaptive_thresh_image = cv.adaptiveThreshold(gray_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 2)
In [ ]:
plt.figure(figsize=(20,30))

plt.subplot(5,3,1)
plt.imshow(mean_filtered_image)
plt.title('Mean Filtered Image')

plt.subplot(5,3,2)
plt.imshow(gaussian_filtered_image)
plt.title('Gaussian Filtered Image')

plt.subplot(5,3,3)
plt.imshow(sobel_left_image)
plt.title('sobel LEft image')

plt.subplot(5,3,4)
plt.imshow(sobel_up_image)
plt.title('Sobel Up Image')

plt.subplot(5,3,5)
plt.imshow(sobel_right_image)
plt.title('Sobel right image')

plt.subplot(5,3,6)
plt.imshow(sobel_down_image)
plt.title('Sobel down image')

plt.subplot(5,3,7)
plt.imshow(median_filtered_image)
plt.title('Median Filtered Image')

plt.subplot(5,3,8)
plt.imshow(abs_laplacian)
plt.title('Laplacian Filter')

plt.subplot(5,3,9)
plt.imshow(bilateral_filtered_image)
plt.title('Bilateral Filtered Image')

plt.subplot(5,3,10)
plt.imshow(dst)
plt.title('NLM Filter Image')

plt.subplot(5,3,11)
plt.imshow(box_filtered_image)
plt.title('Box Filtered Image')

plt.subplot(5,3,12)
plt.imshow(abs_scharrx)
plt.title('Scharr x Filter Image')

plt.subplot(5,3,13)
plt.imshow(abs_scharry)
plt.title('Scharr y Filter Image')

plt.subplot(5,3,14)
plt.imshow(adaptive_thresh_image)
plt.title('Adaptive Thresholding Image')


plt.show()
No description has been provided for this image
In [ ]:
!pip install scikit-image
Requirement already satisfied: scikit-image in /usr/local/lib/python3.10/dist-packages (0.23.2)
Requirement already satisfied: numpy>=1.23 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (1.26.4)
Requirement already satisfied: scipy>=1.9 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (1.13.1)
Requirement already satisfied: networkx>=2.8 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (3.3)
Requirement already satisfied: pillow>=9.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (9.4.0)
Requirement already satisfied: imageio>=2.33 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (2.34.2)
Requirement already satisfied: tifffile>=2022.8.12 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (2024.7.24)
Requirement already satisfied: packaging>=21 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (24.1)
Requirement already satisfied: lazy-loader>=0.4 in /usr/local/lib/python3.10/dist-packages (from scikit-image) (0.4)
In [ ]:
from skimage.metrics import structural_similarity as ssim, mean_squared_error
import numpy as np

# List of filtered images
filtered_images = [
    ("Mean Filter", mean_filtered_image),
    ("Gaussian Filter", gaussian_filtered_image),
    ("Sobel Left Filter", sobel_left_image),
    ("Sobel Right Filter", sobel_right_image),
    ("Sobel Up Filter", sobel_up_image),
    ("Sobel Down Filter", sobel_down_image),
    ("Median Filter", median_filtered_image),
    ("Laplacian Filter", abs_laplacian),
    ("Bilateral Filter", bilateral_filtered_image),
    ("Non-Local Means Filter", dst),
    ("Box Filter", box_filtered_image),
    ("Scharr X Filter", abs_scharrx),
    ("Scharr Y Filter", abs_scharry),
    ("Adaptive Gaussian Threshold", adaptive_thresh_image),
]


# Function to compute SSIM, MSE
def compute_metrics(image1, image2):
    # Convert images to grayscale if they are not already
    if len(image1.shape) == 3 and image1.shape[2] == 3:
        image1_gray = cv.cvtColor(image1, cv.COLOR_BGR2GRAY)
    else:
        image1_gray = image1

    if len(image2.shape) == 3 and image2.shape[2] == 3:
        image2_gray = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)
    else:
        image2_gray = image2

    ssim_value = ssim(image1_gray, image2_gray)
    mse_value = mean_squared_error(image1_gray, image2_gray)
    return ssim_value, mse_value

# Compute SSIM and MSE for each filtered image
similarity_scores = {}
mse_scores = {}
for name, filtered_image in filtered_images:
    ssim_score, mse_score = compute_metrics(image, filtered_image)
    similarity_scores[name] = ssim_score
    mse_scores[name] = mse_score

# Sort the similarity scores in descending order
sorted_similarity_scores = sorted(similarity_scores.items(), key=lambda item: item[1], reverse=True)
sorted_mse_scores = sorted(mse_scores.items(), key=lambda item: item[1])

# Display the sorted list of filters with their SSIM and MSE values
print("Filters sorted by similarity (SSIM) to the original image:")
for name, score in sorted_similarity_scores:
    print(f"{name}: SSIM = {score:.4f}, MSE = {mse_scores[name]:.4f}")

# Identify the filter with the highest similarity
best_match = sorted_similarity_scores[0]
print(f"\nThe filter with the highest similarity is: {best_match[0]} with an SSIM of {best_match[1]:.4f}")

print("\nFilters sorted by dissimilarity (MSE) to the original image:")
for name, score in sorted_mse_scores:
    print(f"{name}: MSE = {score:.4f}, SSIM = {similarity_scores[name]:.4f}")
Filters sorted by similarity (SSIM) to the original image:
Bilateral Filter: SSIM = 0.7733, MSE = 108.0790
Gaussian Filter: SSIM = 0.5769, MSE = 255.6299
Non-Local Means Filter: SSIM = 0.5706, MSE = 191.3123
Median Filter: SSIM = 0.3879, MSE = 414.1358
Mean Filter: SSIM = 0.3806, MSE = 387.0354
Box Filter: SSIM = 0.3806, MSE = 387.0354
Adaptive Gaussian Threshold: SSIM = 0.2573, MSE = 13752.2860
Laplacian Filter: SSIM = 0.0126, MSE = 12653.3059
Sobel Down Filter: SSIM = 0.0115, MSE = 16395.9739
Sobel Up Filter: SSIM = 0.0114, MSE = 16300.5667
Sobel Left Filter: SSIM = 0.0112, MSE = 16453.9052
Sobel Right Filter: SSIM = 0.0103, MSE = 16409.5789
Scharr Y Filter: SSIM = -0.0010, MSE = 15442.2722
Scharr X Filter: SSIM = -0.0023, MSE = 15528.0601

The filter with the highest similarity is: Bilateral Filter with an SSIM of 0.7733

Filters sorted by dissimilarity (MSE) to the original image:
Bilateral Filter: MSE = 108.0790, SSIM = 0.7733
Non-Local Means Filter: MSE = 191.3123, SSIM = 0.5706
Gaussian Filter: MSE = 255.6299, SSIM = 0.5769
Mean Filter: MSE = 387.0354, SSIM = 0.3806
Box Filter: MSE = 387.0354, SSIM = 0.3806
Median Filter: MSE = 414.1358, SSIM = 0.3879
Laplacian Filter: MSE = 12653.3059, SSIM = 0.0126
Adaptive Gaussian Threshold: MSE = 13752.2860, SSIM = 0.2573
Scharr Y Filter: MSE = 15442.2722, SSIM = -0.0010
Scharr X Filter: MSE = 15528.0601, SSIM = -0.0023
Sobel Up Filter: MSE = 16300.5667, SSIM = 0.0114
Sobel Down Filter: MSE = 16395.9739, SSIM = 0.0115
Sobel Right Filter: MSE = 16409.5789, SSIM = 0.0103
Sobel Left Filter: MSE = 16453.9052, SSIM = 0.0112

Comparison of Filters by Similarity (SSIM) and Dissimilarity (MSE)¶

The following tables list various image filters along with their Structural Similarity Index (SSIM) and Mean Squared Error (MSE) scores, which measure the similarity and dissimilarity of the filtered images to the original image, respectively.

Filters Sorted by Similarity (SSIM)¶

Filter SSIM MSE
Bilateral Filter 0.7733 108.0790
Gaussian Filter 0.5769 255.6299
Non-Local Means Filter 0.5706 191.3123
Median Filter 0.3879 414.1358
Mean Filter 0.3806 387.0354
Box Filter 0.3806 387.0354
Adaptive Gaussian Threshold 0.2573 13752.2860
Laplacian Filter 0.0126 12653.3059
Sobel Down Filter 0.0115 16395.9739
Sobel Up Filter 0.0114 16300.5667
Sobel Left Filter 0.0112 16453.9052
Sobel Right Filter 0.0103 16409.5789
Scharr Y Filter -0.0010 15442.2722
Scharr X Filter -0.0023 15528.0601

Filters Sorted by Dissimilarity (MSE)¶

Filter MSE SSIM
Bilateral Filter 108.0790 0.7733
Non-Local Means Filter 191.3123 0.5706
Gaussian Filter 255.6299 0.5769
Mean Filter 387.0354 0.3806
Box Filter 387.0354 0.3806
Median Filter 414.1358 0.3879
Laplacian Filter 12653.3059 0.0126
Adaptive Gaussian Threshold 13752.2860 0.2573
Scharr Y Filter 15442.2722 -0.0010
Scharr X Filter 15528.0601 -0.0023
Sobel Up Filter 16300.5667 0.0114
Sobel Down Filter 16395.9739 0.0115
Sobel Right Filter 16409.5789 0.0103
Sobel Left Filter 16453.9052 0.0112

Key Observations¶

  1. Highest Similarity: Bilateral Filter

    • The Bilateral Filter achieved the highest SSIM score of 0.7733 and the lowest MSE of 108.0790, indicating that it preserves the structural integrity of the original image while effectively smoothing it. This makes it an excellent choice for applications requiring noise reduction while maintaining edge sharpness.
  2. Gaussian Filter and Non-Local Means Filter

    • The Gaussian Filter and Non-Local Means Filter also performed well, with SSIM scores of 0.5769 and 0.5706, and MSE values of 255.6299 and 191.3123, respectively. These filters are good for general smoothing and noise reduction.
  3. Moderate Performance: Median, Mean, and Box Filters

    • The Median Filter, Mean Filter, and Box Filter showed moderate similarity scores around 0.38 and moderate MSE values around 387. These filters are useful for certain types of noise removal but may not preserve edges as well as the Bilateral Filter.
  4. Low Similarity: Edge Detection Filters

    • Filters like the Laplacian, Sobel, and Scharr Filters had very low SSIM scores and high MSE values, indicating low similarity to the original image. These filters are designed for edge detection and highlighting gradients rather than maintaining overall image structure.
  5. Negative Scores: Scharr Filters

    • The Scharr Filters even produced negative SSIM scores, which indicates a significant deviation from the original image structure. These filters are highly specialized for edge detection tasks.

Overall, the Bilateral Filter stands out as the best choice for maintaining the original image's structure while providing effective smoothing and noise reduction.